<!--
 * @Descripttion: 
 * @version: 
 * @Author: wtzhang
 * @Date: 2021-07-21 14:59:37
 * @LastEditors: wtzhang
 * @LastEditTime: 2021-07-21 16:03:03
-->
<template>
  <div class="customRef">
    <h3 class="title">自定义customRef</h3>
    <hr>
    <h4>由ref定义的age：{{age}}</h4><br>
    <button @click="addNum">增加1</button><br><hr>
    <h4>由自定义customRef的sum：{{sum}}</h4><br>
    <button @click="addSum">增加1</button><br><hr>
    <h4>由自定义customRef的debounce</h4>
    <input type="password" v-model="password" ref="inputFocus"><br>
    <p>输入的内容：{{password}}</p>
  </div>
</template>

<script lang="ts">
import { customRef, defineComponent, onMounted, ref } from 'vue'

// 自定义customRef ----> ref
function myCustomRef<T>(value:T) {
  return customRef((track, trigger) => {
    return {
      get(){
        track()
        // console.log('customRef get 执行了。。。', value);
        return value
      },
      set(val:T){
        trigger()
        // console.log('customRef set 执行了。。。', value);
        value = val
      }
    }
  })
}

// 实现函数防抖自定义 ref
function useDebouncedRef<T>(value: T, delay = 200){
  let timer:number;
  return customRef((track, trigger) => {
    return {
      get(){
        track()// 告诉vue追踪此数据
        return value
      },
      set(newVal: T){
        trigger() // 告诉vue去触发界面更新
        clearTimeout(timer)
        timer = setTimeout(() => {
          value = newVal
        }, delay)
      }
    }
  })
}
export default defineComponent ({
  name: 'customRef',
  setup(){
    // ref
    let age = ref(18)
    const addNum = () => {
      console.log(age);
      age.value += 1
    }
    // customRef
    let sum = myCustomRef(10)
    const addSum = () => {
      sum.value += 1
    }
    // 由自定义customRef的debounce
    // 默认是空的，页面加载完毕，说明组件已经存在了，则获取文本框元素
    let inputFocus = ref<HTMLElement | null>(null)
    // 页面加载后的生命周期组合API
    onMounted(() => {
      inputFocus.value && inputFocus.value.focus() // 文本元素存在，自动获取焦点
    })
    let password = useDebouncedRef('', 100)
    console.log(password);
    
    return {
      age,
      sum,
      addNum,
      addSum,
      inputFocus,
      password
    }
  }
})
</script>

<style>
  .customRef {
    padding: 16px;
  }
</style>